<?php
/**********************************************************************************
WIKINDX: Bibliographic Management system.
Copyright (C)

This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program;
if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

The WIKINDX Team 2007
sirfragalot@users.sourceforge.net
**********************************************************************************/
/*****
*	ENDNOTEIMPORTSTAGE2: Endnote XML STAGE2 import class
*
*	$Header: /cvsroot/wikindx/wikindx3/core/file/import/ENDNOTEIMPORTSTAGE2.php,v 1.39 2007/10/16 05:26:58 sirfragalot Exp $
*****/
/*
* @author Mark Grimshaw
* @version 2
*/
class ENDNOTEIMPORTSTAGE2
{
// Constructor
	function ENDNOTEIMPORTSTAGE2($db, $vars)
	{
		$this->db = $db;
		$this->db->escapeString = TRUE;
		$this->vars = $vars;
		include_once("core/session/SESSION.php");
		$this->session = new SESSION();
		include_once("core/messages/MESSAGES.php");
		$this->messages = new MESSAGES();
		include_once("core/messages/ERRORS.php");
		$this->errors = new ERRORS();
		include_once("core/messages/SUCCESS.php");
		$this->success = new SUCCESS();
		include_once("core/file/ENDNOTEMAP.php");
		$this->map = new ENDNOTEMAP();
		include_once("core/resource/RESOURCEMAP.php");
		$this->resourceMap = new RESOURCEMAP();
// need to use English constants for Endnote
		include_once("languages/en/CONSTANTS.php");
		$constants = new CONSTANTS_en();
		$constants->convertNumbers();
		$this->editionNumbers = array_flip($constants->cardinalToOrdinalWord());
		include_once("core/html/MISC.php");
		include_once("core/html/HTML.php");
		$this->html = new HTML();
		include_once("core/html/FORM.php");
		include_once("core/html/TABLE.php");
		include_once("core/file/TAG.php");
		$this->tag = new TAG($this->db);
		include_once("core/file/import/ENDNOTECREATORPARSE.php");
		$this->parseCreator = new ENDNOTECREATORPARSE();
		include_once("core/file/import/ENDNOTEDATEPARSE.php");
		$this->date = new ENDNOTEDATEPARSE();
		include_once("core/file/import/BIBTEXPAGEPARSE.php");
		$this->pages = new BIBTEXPAGEPARSE();
		include_once("core/file/import/IMPORTCOMMON.php");
		$this->common = new IMPORTCOMMON($this->db);
		$this->resourceAdded = $this->resourceDiscarded = 
			$this->resourceAddedThisRound = $this->resourceDiscardedThisRound = 0;
		$this->creators = array('creator1', 'creator2', 'creator3', 'creator4', 'creator5');
		$this->oldTime = time();
	}
/*
* init - start the process
* 
* @author Mark Grimshaw
* @param string $message - optional error message
* @return string
*/
	function init($message = FALSE)
	{
// if session variable 'importLock' is TRUE, user is simply reloading this form
		if($this->session->getVar('importLock'))
			$this->badInput($this->errors->text("done", "fileImport"));
		$this->fileName = $this->gatherStage1();
		$this->rejectTitles = $this->entries = $this->rejects = $this->inputTypes = array();
		include_once("core/file/import/ENDNOTEPARSEXML.php");
		$parse = new ENDNOTEPARSEXML();
		if(!$this->session->getVar("import_unrecognisedFields"))
		{
			$parse->openFile($this->fileName);
			$parse->extractEntries();
			$parse->closeFile();
			$entries = $parse->returnArrays();
			if(empty($entries))
			{
				$pString = MISC::p($this->messages->text("import", "empty"));
				$this->session->setVar('importLock', TRUE);
				return $pString;
			}
			$this->version8 = $parse->version8;
			$this->endnoteVersion();
			foreach($entries as $key => $entry)
			{
				$this->entry = $this->reject = array();
				if($this->convertEntries($entry))
					$this->entries[$key] = $this->entry;
				if(!empty($this->reject))
					$this->rejects[$key] = $this->reject;
			}
		}
		else
		{
			$this->version8 = $this->session->getVar("import_version8");
			if($this->session->issetVar("import_rejects"))
				$this->rejects = unserialize(base64_decode($this->session->getVar("import_rejects")));
			$this->endnoteVersion();
			list($this->vars, $null, $this->customFields, $this->entries, $this->unrecognisedFields) = 
				$this->common->stage3($this->vars, $this);
		}
		if(empty($this->entries))
		{
			$pString = MISC::p($this->messages->text("import", "empty"));
			$this->session->setVar('importLock', TRUE);
			return $pString;
		}
		if($this->version8 && !empty($this->rejects) && !$this->session->getVar("import_unrecognisedFields"))
		{
			if($pString = $this->findInvalidFields())
				return $pString;
		}
		$this->entriesLeft = $this->entries;
//print_r($entries); print "<P>";
		$finalInput = $this->writeDb();
		return $this->cleanUp($finalInput);
	}
/**
* find unrecognised field names
* 
* @author Mark Grimshaw
*/
	function findInvalidFields()
	{
		$this->invalidFieldNames = array();
		if(!empty($this->inputTypes))
			$this->inputTypes = array_unique($this->inputTypes);
		$this->day = $this->month = FALSE;
		foreach($this->rejects as $reject)
		{
			foreach($reject as $field => $value)
			{
				if(($field == 'source-app') || ($field == 'ref-type'))
					continue;
				if(array_search($field, $this->invalidFieldNames) === FALSE)
					$this->invalidFieldNames[] = $field;
			}
		}
		if(!empty($this->rejects))
			$this->session->setVar("import_rejects", base64_encode(serialize($this->rejects)));
		if(!empty($this->invalidFieldNames)) // prompt to map field names
			return $this->common->promptFieldNames($this->entries, $this->inputTypes, $this->vars, $this->map, 
				$this->invalidFieldNames, FALSE, $this);
		return FALSE; // continue with import.
	}
/**
* Continue an import
*
*/
	function continueImport()
	{
		if($this->session->issetVar("import_rejectTitles"))
			$this->rejectTitles = unserialize(base64_decode($this->session->getVar("import_rejectTitles")));
		else
			$this->rejectTitles = array();
		if($this->session->issetVar("import_rejects"))
			$this->rejects = unserialize(base64_decode($this->session->getVar("import_rejects")));
// Restore session
// Number added so far
		$this->resourceAdded = $this->session->getVar("import_resourceAdded");
// Number discarded so far
		$this->resourceDiscarded = $this->session->getVar("import_resourceDiscarded");
// Endnote version
		$this->version8 = $this->session->getVar("import_version8");
// tag ID
		if($this->session->issetVar("import_tagID"))
			$this->tagId = $this->session->getVar("import_tagID");
// import types
		$this->importTypes = unserialize(base64_decode($this->session->getVar("import_importTypes")));
// xml fields
		$this->endnoteXmlFields = unserialize(base64_decode($this->session->getVar("import_endnoteXmlFields")));
		$this->entriesLeft = $this->entries = 
			unserialize(base64_decode($this->session->getVar("import_entries")));
		if($this->session->issetVar("import_unrecognisedFields"))
		{
			$this->unrecognisedFields = 
				unserialize(base64_decode($this->session->getVar("import_unrecognisedFields")));
			$this->customFields = unserialize(base64_decode($this->session->getVar("import_customFields")));
			$this->vars = unserialize(base64_decode($this->session->getVar("import_thisVars")));
		}
		$finalInput = $this->writeDb(TRUE);
		return $this->cleanUp($finalInput);
	}
/**
* Garbage clean up and intermediate session saving when importing in chunks
*
*/
	function cleanUp($finalInput)
	{
// update total no. resources in summary table
		$recordset = $this->db->select(array('WKX_database_summary'), array("totalResources"));
		$totalResources = $this->db->fetchOne($recordset) + $this->resourceAddedThisRound;
		$this->db->update('WKX_database_summary', array("totalResources" => $totalResources));
		if($finalInput)
		{
			@unlink($this->fileName); // remove garbage - ignore errors
			$pString = MISC::p($this->success->text("endnoteImport"));
			$pString .= MISC::p($this->messages->text("import", "added", " " . $this->resourceAdded));
			$pString .= $this->common->printDuplicates($this->resourceDiscarded, $this->rejectTitles);
			$this->session->setVar('importLock', TRUE);
		}
		else
		{
// Store temporary session variables
// Number added
			$this->session->setVar("import_resourceAdded", $this->resourceAdded);
// Number of rejects
			$this->session->setVar("import_resourceDiscarded", $this->resourceDiscarded);
// Endnote version
			$this->session->setVar("import_version8", $this->version8);
// tag ID
			if(isset($this->tagId))
				$this->session->setVar("import_tagID", $this->tagId);
// Remaining entries
			$this->session->setVar("import_entries", base64_encode(serialize($this->entriesLeft)));
// Rejected titles
			if(!empty($this->rejectTitles))
				$this->session->setVar("import_rejectTitles", base64_encode(serialize($this->rejectTitles)));
// Rejected fields
			if(!empty($this->rejects))
				$this->session->setVar("import_rejects", base64_encode(serialize($this->rejects)));
// import types
			$this->session->setVar("import_importTypes", base64_encode(serialize($this->importTypes)));
// xml fields
			$this->session->setVar("import_endnoteXmlFields", base64_encode(serialize($this->endnoteXmlFields)));
// Unrecognised field mapping
			if(isset($this->unrecognisedFields))
			{
				$this->session->setVar("import_unrecognisedFields", 
					base64_encode(serialize($this->unrecognisedFields)));
// Custom field mapping
				if(isset($this->customFields))
					$this->session->setVar("import_customFields", base64_encode(serialize($this->customFields)));
// $this->vars
				$this->session->setVar("import_thisVars", 
					base64_encode(serialize($this->vars)));
			}
			$remainder = sizeof($this->entriesLeft);
			$pString = MISC::p($this->messages->text("import", "executionTimeExceeded", 
				ini_get("max_execution_time")));
			$pString .= MISC::p($this->messages->text("import", "addedChunk", " " . 
				$this->resourceAddedThisRound));
			$pString .= MISC::p("$remainder entries remaining.");
			$pString .= FORM::formHeader("importEndnoteStage2Continue");
			$pString .= MISC::p(FORM::formSubmit("Continue"));
			$pString .= FORM::formEnd();
		}
		return $pString;
	}
/*
* endnoteVersion - Endnote versions earlier than 8.0 have a _very_ different XML format and 
* type naming to version 8.0 *&^$*&^!  Load appropriate mapping arrays
* 
* @author Mark Grimshaw
*
* @param	$version8 TRUE/FALSE
*/
	function endnoteVersion()
	{
		if($this->version8)
		{
			$this->importTypes = $this->map->importTypes8;
			$this->endnoteXmlFields = $this->map->endnoteXmlFields8;
		}
		else
		{
			$this->importTypes = $this->map->importTypesPre8;
			$this->endnoteXmlFields = $this->map->endnoteXmlFieldsPre8;
		}
	}
/*
* writeDb - write input to the database.
* 
* @author Mark Grimshaw
* @param $entries - multi-array of XML entries
*/
	function writeDb($continue = FALSE)
	{
		$tagWritten = FALSE;
		if(!$continue)
			$this->tagId = FALSE;
		$finalInput = TRUE;
		foreach($this->entries as $key => $entry)
		{
			$custom = $this->collectionStringArray = array();
			unset($this->entriesLeft[$key]);
			$this->entry = $entry;
			if(isset($this->unrecognisedFields))
			{
				foreach($this->unrecognisedFields as $field)
				{
					if(!array_key_exists($field, $this->rejects[$key]))
						continue;
					if(array_key_exists($field, $this->rejects[$key]) && 
						array_key_exists($field, $this->customFields))
					{
						$custom[$field] = $this->rejects[$key][$field];
						unset($this->rejects[$key][$field]);
						continue;
					}
					$importField = "import_$field";
					if(array_key_exists($importField, $this->vars) && 
						($this->vars[$importField] != $this->messages->text('misc', 'ignore')))
					{
						$wField = $this->vars[$importField];
						foreach($this->map->{$this->entry['type']} as $arrayName => $array)
						{
							if($arrayName == 'possible')
								continue;
							if(($wKey = array_search($wField, $array)) !== FALSE)
							{
	// standard field takes precedence over unknown
								if(array_key_exists($arrayName, $this->entry) && 
									array_key_exists($wKey, $this->entry[$arrayName]) && 
									!array_key_exists('import_precedence', $this->vars))
									continue;
								$this->entry[$arrayName][$wKey] = $this->rejects[$key][$field];
								break;
							}
						}
					}
				}
			}
// If type == 'book' or 'book_article', need to swap 'year1' (WIKINDX's original publication year) and 
// 'year2' (WIKINDX's reprint year)
			if((($this->entry['type'] == 'book') || ($this->entry['type'] == 'book_article')) && 
				isset($this->entry['resource_year']['year1']) 
				&& isset($this->entry['resource_year']['year2']))
			{
				$year2 = $this->entry['resource_year']['year2'];
				$this->entry['resource_year']['year2'] = $this->entry['resource_year']['year1'];
				$this->entry['resource_year']['year1'] = $year2;
			}
			foreach($this->creators as $creatorType)
			{
				$$creatorType = array();
				if(array_key_exists($creatorType, $this->entry))
				{
					$creators = join(" and ", $this->entry[$creatorType]);
					$$creatorType = $this->parseCreator->parse($creators);
//print_r($$creatorType); print "<P>";
				}
			}
// For duplicate checking, we try to find the surname of the primary creator ($creator1[0][2] is the surname)
			if(!empty($creator1) && array_key_exists(0, $creator1) && $creator1[0][2])
				$creatorSurname = $creator1[0][2];
			else
				$creatorSurname = FALSE;
//print "CREATOR: $creatorSurname<P>";
			if(!$this->session->getVar('import_importDuplicates') && 
				$this->common->titleExists($this->entry['title'], trim($creatorSurname), 
				$this->entry['type']))
			{
				$rejectTitle = $this->entry['title'] . ".";
				if(array_key_exists('creator1', $this->entry) && $this->entry['creator1'])
					$rejectTitle = trim(join(", ", $this->entry['creator1'])) . " " . $rejectTitle;
				$this->rejectTitles[] = $rejectTitle;
				$this->resourceDiscarded++;
				$this->resourceDiscardedThisRound++;
				continue;
			}
			$this->publisherId = $this->collectionId = FALSE;
			$this->grabMonth($this->entry['type']);
//print_r($this->entry); print "<P>";
//print_r($this->reject); print "<P>";
			$this->resourceId = $this->writeResourceTable();
			$addedResourceIds[] = $this->resourceId;
// add any import tag and get tag auto ID.  We write it here after the resource table in case we forbid duplicates and all 
// endnote entries are duplicates - we don't want an empty tag in the WKX_tag table.
			if(!$continue)
			{
				if(!$tagWritten)
				{
					$this->tagId = $this->writeTagTable();
					$tagWritten = TRUE;
				}
			}
			foreach($this->creators as $creatorType)
			{
				if(!empty($$creatorType))
					$this->creatorList[$creatorType] = $this->writeCreatorTable($$creatorType);
				else if(isset($this->creatorList))
					unset($this->creatorList[$creatorType]);
//				unset($$creatorType);
			}
			$this->writeResourceCreatorTable();
			$this->writePublisherTable();
			$this->writeResourceMiscTable();
			$this->writeResourceYearTable();
			$this->writeResourcePageTable();
			$this->writeResourceKeywordTable();
			if(!empty($custom))
				$this->writeResourceCustomTable($custom);
			$this->writeResourceCategoryTable();
			$this->writeCollectionTable();
			$this->writeResourceNoteTable();
			$this->writeResourceAbstractTable();
			$this->writeResourceTimestampTable();
			$this->writeImportRawTable();
			$this->writeBibtexKey();
			$this->resourceAdded++;
			$this->resourceAddedThisRound++;
// Check we have more than 5 seconds buffer before max_execution_time times out.
			if((time() - $this->oldTime) >= (ini_get("max_execution_time") - 5))
			{
				$finalInput = FALSE;
				break;
			}
		}
// email notification
		if(isset($addedResourceIds))
		{
			$this->common->bibliographyAdd($addedResourceIds);
			$this->common->notify($addedResourceIds);
		}
		return $finalInput;
	}
/*
* writeResourceTable - write WKX_resource table and get lastAutoId
* @author Mark Grimshaw
*
* @return autoId
*/
	function writeResourceTable()
	{
// If there's nothing saying whether a thesis is a thesis or a dissertation, here we force it to 'thesis'.
		if($this->entry['type'] == 'thesis')
		{
			$fields[] = 'field1';
			$values[] = 'thesis';
			$this->collectionStringArray['field1'] = 'thesis';
		}
		$fields[] = 'type';
		$values[] = $this->entry['type'];
		list($noSort, $title, $subtitle) = $this->common->splitTitle($this->entry['title']);
		$fields[] = 'title';
		$values[] = $title;
		if($noSort)
		{
			$fields[] = 'noSort';
			$values[] = $noSort;
		}
		if($subtitle)
		{
			$fields[] = 'subtitle';
			$values[] = $subtitle;
		}
		if(array_key_exists('resource', $this->entry))
		{
			foreach($this->entry['resource'] as $field => $value)
			{
				if(($this->entry['type'] == 'thesis') && ($field == 'field1'))
					continue;
				$fields[] = $field;
				$values[] = $value;
				$this->collectionStringArray[$field] = $value;
			}
		}
		$this->db->insert('WKX_resource', $fields, $values);
		return $this->db->lastAutoID('WKX_resource');
	}
/*
* writeCreatorTable - write WKX_creator table and get lastAutoId
* @author Mark Grimshaw
*
* @param $creators - assoc array of creators for one entry
* @return comma-separated list of creator IDs ready for insertion into WKX_resource_creator table.
*/
	function writeCreatorTable($creators)
	{
		if(!$creators)
			return FALSE;
		foreach($creators as $array)
		{
			$prefix = trim($array[3]);
			$surname = trim($array[2]);
			$firstname = trim($array[0]);
			$initials = trim($array[1]);
			$creatorIds[] = $this->common->writeCreatorTable($firstname, $initials, $prefix, $surname);
		}
		return implode(',', $creatorIds);
	}
/*
* writeResourceCreatorTable - write to WKX_resource_creator table
* @author Mark Grimshaw
*
*/
	function writeResourceCreatorTable()
	{
		if(!isset($this->creatorList))
			return;
		foreach($this->creatorList as $creatorType => $list)
		{
			$fields[] = $creatorType;
			$values[] = $list;
			if($creatorType != 'creator1')
				$this->collectionStringArray[$creatorType] = $list;
		}
		if(!isset($fields))
			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$this->db->insert('WKX_resource_creator', $fields, $values);
	}
/*
* writeCollectionTable - write WKX_collection table
* @author Mark Grimshaw
*
*/
	function writeCollectionTable()
	{
		if(!array_key_exists('resource_collection', $this->entry))
			return;
		$title = $short = FALSE;
		if(array_key_exists('collectionTitle', $this->entry['resource_collection']))
			$title = trim($this->entry['resource_collection']['collectionTitle']);
		if(array_key_exists('collectionTitleShort', $this->entry['resource_collection']))
			$short = trim($this->entry['resource_collection']['collectionTitleShort']);
		if(!$title)
			return;
		$this->collectionStringArray['type'] = $this->entry['type'];
		$this->collectionStringArray['collection'] = $title;
		$this->collectionStringArray['collectionShort'] = $short;
		$this->collectionId = $this->common->writeCollectionTable($this->collectionStringArray, 
			$this->publisherId);
// update this resource_misc table row with the collectionId
		$this->db->update('WKX_resource_misc', array('collection' => $this->collectionId), 
			' WHERE ' . $this->db->formatField('id') . '=' . $this->db->tidyInput($this->resourceId));
	}
/*
* writePublisherTable - write WKX_publisher table
* @author Mark Grimshaw
*
*/
	function writePublisherTable()
	{
		if(!array_key_exists('resource_publisher', $this->entry))
			return;
		$publisherName = $publisherLocation = FALSE;
		if(array_key_exists('publisherName', $this->entry['resource_publisher']))
			$publisherName = trim($this->entry['resource_publisher']['publisherName']);
		if(array_key_exists('publisherLocation', $this->entry['resource_publisher']))
			$publisherLocation = trim($this->entry['resource_publisher']['publisherLocation']);
		if(!$publisherName)
			return;
		$this->publisherId = $this->common->writePublisherTable($publisherName, $publisherLocation, 
			$this->entry['type']);
	}
/*
* writeResourceMiscTable - write WKX_resource_misc table
* @author Mark Grimshaw
*
*/
	function writeResourceMiscTable()
	{
		if(array_key_exists('resource_misc', $this->entry))
		{
			foreach($this->entry['resource_misc'] as $field => $value)
			{
				$fields[] = $field;
				$values[] = $value;
				$this->collectionStringArray[$field] = $value;
			}
		}
		if($this->collectionId)
		{
			$fields[] = 'collection';
			$values[] = $this->collectionId;
		}
		if($this->publisherId)
		{
			$fields[] = 'publisher';
			$values[] = $this->publisherId;
		}
		if($this->tagId)
		{
			$fields[] = 'tag';
			$values[] = $this->tagId;
		}
//		if(!isset($fields))
//			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$fields[] = 'addUserIdResource';
		$values[] = $this->session->getVar("setup_userId");
		$this->db->insert('WKX_resource_misc', $fields, $values);
	}
/*
* writeResourceYearTable - write WKX_resource_year table
* @author Mark Grimshaw
*
*/
	function writeResourceYearTable()
	{
		if(array_key_exists('resource_year', $this->entry))
		{
			foreach($this->entry['resource_year'] as $field => $value)
			{
				$fields[] = $field;
				$values[] = $value;
				$this->collectionStringArray[$field] = $value;
			}
		}
		if(!isset($fields))
			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$this->db->insert('WKX_resource_year', $fields, $values);
	}
/*
* writeResourcePageTable - write WKX_resource_page table
* @author Mark Grimshaw
*
*/
	function writeResourcePageTable()
	{
		if(!array_key_exists('pageStart', $this->entry))
			return;
		$fields[] = 'pageStart';
		$values[] = $this->entry['pageStart'];
		if(array_key_exists('pageEnd', $this->entry))
		{
			$fields[] = 'pageEnd';
			$values[] = $this->entry['pageEnd'];
		}
		if(!isset($fields))
			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$this->db->insert('WKX_resource_page', $fields, $values);
	}
/*
* writeResourceNoteTable - write WKX_resource_note table
* @author Mark Grimshaw
*
*/
	function writeResourceNoteTable()
	{
		if(array_key_exists('notes', $this->entry))
		{
			$fields[] = 'text';
			$values[] = $this->entry['notes'];
		}
		if(!isset($fields))
			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$fields[] = 'addUserIdNote';
		$values[] = $this->session->getVar("setup_userId");
		$this->db->insert('WKX_resource_note', $fields, $values);
	}
/*
* writeResourceAbstractTable - write WKX_resource_abstract table
* @author Mark Grimshaw
*
*/
	function writeResourceAbstractTable()
	{
		if(array_key_exists('abstract', $this->entry))
		{
			$fields[] = 'abstract';
			$values[] = $this->entry['abstract'];
		}
		if(!isset($fields))
			return;
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$fields[] = 'addUserIdAbstract';
		$values[] = $this->session->getVar("setup_userId");
		$this->db->insert('WKX_resource_abstract', $fields, $values);
	}
/*
* writeResourceKeywordTable - write WKX_resource_keyword table
* @author Mark Grimshaw
*
*/
	function writeResourceKeywordTable()
	{
		if(array_key_exists('keywords', $this->entry))
		{
			$keywords = join(';', $this->entry['keywords']);
			$this->common->writeResourceKeywordTable($keywords, $this->resourceId, 1);
		}
	}
/*
* writeResourceCategoryTable - write WKX_resource_category table
* @author Mark Grimshaw
* @param $entry - assoc array of one entry for import.
*/
	function writeResourceCategoryTable()
	{
		if(!$groups = $this->session->getVar('import_groups'))
			$groups = 1; // force to 'General' category
		$this->db->insert('WKX_resource_category', array('id', 'categories'), 
			array($this->resourceId, $groups));
	}
/*
* writeImportRawTable - write WKX_import_raw table
* @author Mark Grimshaw
*/
	function writeImportRawTable()
	{
		if(empty($this->reject) || !$this->session->getVar("import_raw"))
			return;
		$rejected = '';
		foreach($this->reject as $key => $value)
		{
			if(($key == 'source-app') || ($key == 'ref-type'))
				continue;
//			if(array_key_exists($key, $this->endnoteXmlFields))
//				$rejected .= $this->endnoteXmlFields[$key] . " = $value\n";
				$rejected .= $key . " = $value\n";
		}
		$fields[] = 'id';
		$values[] = $this->resourceId;
		$fields[] = 'text';
		$values[] = base64_encode(serialize($rejected));
		$fields[] = 'importType';
		$values[] = 'endnote';
		$sql = $this->db->insert('WKX_import_raw', $fields, $values);

	}
/*
* writeTagTable - write import tag to WKX_tag table
* 
* @author Mark Grimshaw
* @return lastAutoId
*/
	function writeTagTable()
	{
		if($tagId = $this->session->getVar('import_tagId'))
			return $tagId;
		if(!$tag = $this->session->getVar('import_tag'))
			return FALSE;
		$this->db->insert('WKX_tag', array('tag'), array($this->html->removeNl($tag)));
		return $this->db->lastAutoID('WKX_tag');
	}
/*
* writeResourceTimestampTable - write timestamp to WKX_resource_timestamp table
* 
* @author Mark Grimshaw
*/
	function writeResourceTimestampTable()
	{
		$this->db->insert('WKX_resource_timestamp', array('id', 'timestamp', 'timestampAdd'), 
			array($this->resourceId, $this->db->formatTimestamp(), $this->db->formatTimestamp()));
	}
/*
* writeResourceCustomTable - write WKX_resource_custom table
* @author Mark Grimshaw
*
* @param $entry - assoc array of one entry for import.
*/
	function writeResourceCustomTable($custom)
	{
		if(empty($this->customFields))
			return;
		foreach($this->customFields as $importKey => $id)
		{
			if(!array_key_exists($importKey, $custom))
				continue;
			$fields = $values = array();
			$resultSet = $this->db->select(array('WKX_custom'), array('custom_size'), 
				" WHERE " . $this->db->formatField('id') . "=" . $this->db->tidyInput($id));
			$size = $this->db->fetchOne($resultSet);
			$size = $size == 'L' ? 'custom_long' : 'custom_short';
			$fields[] = "customId";
			$values[] = $id;
			$fields[] = "resourceId";
			$values[] = $this->resourceId;
			$fields[] = $size;
			$values[] = $custom[$importKey];
			$fields[] = 'addUserIdCustom';
			$values[] = $this->session->getVar("setup_userId");
			$this->db->insert('WKX_resource_custom', $fields, $values);
		}
	}
/*
* grabMonth - check for any month field and split into component day/month fields
* 
* @author Mark Grimshaw
* @param string $type - WIKINDX resource type
*/
	function grabMonth($type)
	{
		if(array_key_exists('date', $this->entry))
		{
			list($month, $day, $year) = $this->date->init($this->entry['date']);
			if($month and (array_search('miscField3', $this->resourceMap->{$type}['possible']) !== FALSE))
				$this->entry['resource_misc']['miscField3'] = $month;
			if($day and (array_search('miscField2', $this->resourceMap->{$type}['possible']) !== FALSE))
				$this->entry['resource_misc']['miscField2'] = $day;
			if($year and (array_search('year2', $this->resourceMap->{$type}['possible']) !== FALSE))
				$this->entry['resource_year']['year2'] = $year;
			if(!$day && !$month && !$year)
				$this->reject['Date'] = $this->entry['date'];
			unset($this->entry['date']);
		}
	}
/*
* gatherStage1 - gather input from stage 1 and return a fullpath filename for parsing.
* 
* @author Mark Grimshaw
* @return string
*/
	function gatherStage1()
	{
// reset the session variable finalise flag
		$this->session->setVar('importLock', FALSE);
// bibtex_groups is a multiple select box so handle as array
		if(isset($this->vars['import_groups']) && $this->vars['import_groups'])
		{
			if($this->session->getVar("import_unrecognisedFields"))
				$this->vars['import_groups'] = explode(',', $this->vars['import_groups']);
			if(!$this->session->setVar('import_groups', trim(implode(',', $this->vars['import_groups']))))
				$this->badInput($this->errors->text("sessionError", "write"));
		}
// bib_ids is a multiple select box so handle as array
		if(isset($this->vars['import_bib_ids']) && $this->vars['import_bib_ids'])
		{
			if($this->session->getVar("import_unrecognisedFields"))
				$this->vars['import_bib_ids'] = explode(',', $this->vars['import_bib_ids']);
			if(!$this->session->setVar('import_bib_ids', trim(implode(',', $this->vars['import_bib_ids']))))
				$this->badInput($this->errors->text("sessionError", "write"));
		}
		if(isset($this->vars['import_raw']) && $this->vars['import_raw'])
		{
			if(!$this->session->setVar('import_raw', 1))
				$this->badInput($this->errors->text("sessionError", "write"));
		}
		if(isset($this->vars['import_importDuplicates']) && $this->vars['import_importDuplicates'])
		{
			if(!$this->session->setVar('import_importDuplicates', 1))
				$this->badInput($this->errors->text("sessionError", "write"));
		}
// Force to 1 => 'General' group
		else if(!$this->session->getVar('import_groups'))
		{
			if(!$this->session->setVar('import_groups', 1))
				$this->badInput($this->errors->text("sessionError", "write"));
		}
		$dirName = "files/";
		if(!$this->session->getVar("import_unrecognisedFields"))
		{
			if(!isset($_FILES['import_file']))
			{
				if($file = $this->session->getVar('import_file'))
					return $dirName . $file;
				else
					$this->badInput($this->errors->text("file", "upload"));
			}
// Check for file input
			$fileName = sha1(session_id() . $_FILES['import_file']['name']);
			if(!move_uploaded_file($_FILES['import_file']['tmp_name'], $dirName . $fileName))
				$this->badInput($this->errors->text("import_file", "upload"));
			if(!$this->session->setVar('import_file', $_FILES['import_file']['name']))
				$this->badInput($this->errors->text("sessionError", "write"));
			if($this->vars['import_tag'])
			{
				if(!$tagId = $this->tag->checkExists($this->vars['import_tag']))
				{
					if(!$this->session->setVar('import_tag', $this->vars['import_tag']))
						$this->badInput($this->errors->text("sessionError", "write"));
				}
				else
				{
					if(!$this->session->setVar('import_tagId', $tagId))
						$this->badInput($this->errors->text("sessionError", "write"));
				}
			}
			else if(isset($this->vars['import_tagId']) && $this->vars['import_tagId'])
			{
				if(!$this->session->setVar('import_tagId', $this->vars['import_tagId']))
					$this->badInput($this->errors->text("sessionError", "write"));
			}
			return $dirName . $fileName;
		}
	}
/*
* convertEntries - convert values to UTF-8 ready for storing in the database, tidy up the array presentation
* and remove unwanted values.
* 
* @author Mark Grimshaw
* @param string $entry - multidimensional array of one endnote record
* @return multidimensional array of converted records.
*/
	function convertEntries($entry)
	{
		if(!array_key_exists('_ELEMENTS', $entry) || !is_array($entry['_ELEMENTS']))
			return FALSE;
// Need to grab resource type first
		$type = FALSE;
		foreach($entry['_ELEMENTS'] as $key => $value)
		{
			if($value['_NAME'] == 'ref-type') // Endnote v8
			{
				$this->inputTypes[] = $value['_ATTRIBUTES']['name'];
// Endnote's 'Edited Book' type is WIKINDX's 'book'
				if($value['_ATTRIBUTES']['name'] == 'Edited Book')
					$type = $this->entry['type'] = 'book';
				else
					$type = $this->entry['type'] = array_search($value['_ATTRIBUTES']['name'], 
						$this->importTypes);
				break;
			}
// Endnote pre-v8
			else if(($value['_NAME'] == 'REFERENCE_TYPE') && array_key_exists('_DATA', $value))
			{
// Endnote's 'Edited Book' type is WIKINDX's 'book'
				if($value['_DATA'] == 9)
					$type = $this->entry['type'] = 'book';
				else
					$type = $this->entry['type'] = 
						array_search($value['_DATA'], $this->importTypes);
				break;
			}
		}
		if(!$type)
			return FALSE;
		unset($entry[$key]);
		$this->accessYear = $this->accessDate = FALSE;
		foreach($entry['_ELEMENTS'] as $key => $value)
		{
// Transform ISO-8859-1 strings to UTF-8 - web browser encoding is set to UTF-8.  This is fine for form input 
// and means that such input is stored in the db as UTF-8 but text file input (as here) requires an 
// explicit conversion.
			if(is_array($value))
				$this->extractEntries($key, $value, $type);
		}
		if($this->accessYear && $this->accessDate)
			$this->entry['date'] = $this->accessDate . ' ' . $this->accessYear;
		return TRUE;
	}
/*
* extractEntries() - parse multi-array extracting values
*
* @author Mark Grimshaw
* @param $key - array index
* @param $value - array element (array())
* @param $type - WIKINDX resource type
* @return list($name, $data)
*/
	function extractEntries($key, $value, $type)
	{
		$mapped = FALSE;
		if(is_array($value) && array_key_exists("_NAME", $value) && array_key_exists("_DATA", $value))
		{
			if((($value['_NAME'] == 'pages') || ($value['_NAME'] == 'PAGES')) && 
				(array_search('pageStart', $this->resourceMap->{$type}['possible']) !== FALSE))
			{
				list($this->entry['pageStart'], $this->entry['pageEnd']) = 
					$this->pages->init($value['_DATA']);
				return;
			}
// Endnote stores the last update date in pub-dates and access year in volume and access date in number for its 
// Electronic Source.  We want the last two if $type == 'web_article or 'database' and don't want 'pub-dates'.
			else if((($value['_NAME'] == 'volume') || ($value['_NAME'] == 'VOLUME')) && 
				(($type == 'web_article') || ($type == 'database')))
			{
				$this->accessYear = trim($value['_DATA']);
				return;
			}
			else if((($value['_NAME'] == 'number') || ($value['_NAME'] == 'NUMBER')) && 
				(($type == 'web_article') || ($type == 'database')))
			{
				$this->accessDate = trim($value['_DATA']);
				return;
			}
			foreach($this->map->$type as $mapTable => $mapArray)
			{
				if(array_key_exists($value['_NAME'], $this->endnoteXmlFields) && 
					($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], $mapArray)))
				{
					$mapped = TRUE;
					$this->entry[$mapTable][$mapKey] = $value['_DATA'];
					break;
				}
			}
			if(($value['_NAME'] == 'abstract') || ($value['_NAME'] == 'notes') || 
				($value['_NAME'] == 'ABSTRACT') || ($value['_NAME'] == 'NOTES'))
			{
				$mapped = TRUE;
				$this->entry[$value['_NAME']] = $value['_DATA'];
			}
			if(!$mapped)
				$this->reject[$value['_NAME']] = $value['_DATA'];
		}
		if($mapped)
			return;
		if($this->version8)
		{
			if(is_array($value) && array_key_exists("_NAME", $value) 
				 && array_key_exists("_ELEMENTS", $value) && ($value['_NAME'] == 'contributors'))
				$this->extractContributors($value['_ELEMENTS'], $type);
			else if(is_array($value) && array_key_exists("_NAME", $value) 
				 && array_key_exists("_ELEMENTS", $value) && ($value['_NAME'] == 'urls'))
				$this->extractUrl($value['_ELEMENTS'], $type);
			else if(is_array($value) && array_key_exists("_NAME", $value) 
				 && array_key_exists("_ELEMENTS", $value) && 
				(($value['_NAME'] == 'titles') || ($value['_NAME'] == 'dates')))
				$this->extractSecondOrder($value['_ELEMENTS'], $type);
		}
		else
		{
			if(is_array($value) && array_key_exists("_NAME", $value) 
				 && array_key_exists("_ELEMENTS", $value) && 
				(($value['_NAME'] == 'AUTHORS') || ($value['_NAME'] == 'SUBSIDIARY_AUTHORS') || 
				($value['_NAME'] == 'TERTIARY_AUTHORS') || ($value['_NAME'] == 'SECONDARY_AUTHORS')))
					$this->extractAuthors($value['_ELEMENTS'], $type);
			else if(is_array($value) && array_key_exists("_NAME", $value) && 
				($value['_NAME'] == 'TITLE') && array_key_exists("_DATA", $value))
			$this->entry['title'] = $value['_DATA'];
		}
		if(is_array($value) && array_key_exists("_NAME", $value) 
			 && array_key_exists("_ELEMENTS", $value) && 
			(($value['_NAME'] == 'keywords') || ($value['_NAME'] == 'KEYWORDS')))
				$this->extractKeywords($value['_ELEMENTS'], $type);
	}
/* extractSecondOrder() - 3D arrays
*
* @author Mark Grimshaw
* @param $array - array of arrays
* @param $type - WIKINDX resource type
*
*/
	function extractSecondOrder($array, $type)
	{
		foreach($array as $value)
		{
			if(array_key_exists("_NAME", $value) && array_key_exists("_DATA", $value))
			{
				if($value['_NAME'] == 'title')
				{
					$this->entry['title'] = $value['_DATA'];
					continue;
				}
// Endnote stores a patent's international author in the tertiary-title field and the international title 
// in the tertiary-author field.  Why I ask you?
				if(($type == 'patent') && 
					($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
					$this->map->{$type}['resource_creator'])) && 
					($value['_NAME'] == 'tertiary-title'))
				{
					$this->entry[$mapKey][] = $value['_DATA'];
					continue;
				}
				$mapped = FALSE;
				foreach($this->map->$type as $mapTable => $mapArray)
				{
					if(array_key_exists($value['_NAME'], $this->endnoteXmlFields) && 
						($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
						$mapArray)))
					{
						$mapped = TRUE;
						$this->entry[$mapTable][$mapKey] = $value['_DATA'];
						break;
					}
				}
				if(!$mapped)
					$this->reject[$value['_NAME']] = $value['_DATA'];
			}
// Endnote stores the last update date in pub-dates and access year in volume and access date in number for its 
// Electronic Source.  We want the last two if $type == 'web_article or 'database' and don't want 'pub-dates'.
			if(array_key_exists("_NAME", $value) && ($value['_NAME'] == 'pub-dates') &&
				array_key_exists("_ELEMENTS", $value))
			{
				if(($type != 'web_article') && ($type != 'database'))
				{
					foreach($value['_ELEMENTS'] as $date)
					{
						if(
							array_key_exists('_DATA', $date) && 
							($date['_NAME'] == 'date'))
						{
							$this->entry['date'] = $date['_DATA'];
							continue;
						}
						$this->reject[$date['_NAME']] = $date['_DATA'];
					}
				}
			}
		}
	}
/* extractKeywords()
*
* @author Mark Grimshaw
* @param $array - array of arrays
* @param $type - WIKINDX resource type
*
*/
	function extractKeywords($array, $type)
	{
		foreach($array as $value)
		{
			if(array_key_exists("_NAME", $value) && array_key_exists("_DATA", $value))
				$this->entry['keywords'][] = $value['_DATA'];
		}
	}
/* extractAuthors()
*
* @author Mark Grimshaw
* @param $array - array of primary authors
* @param $type - WIKINDX resource type
*
*/
	function extractAuthors($array, $type)
	{
		foreach($array as $value)
		{
			if(array_key_exists("_NAME", $value) && array_key_exists("_DATA", $value))
			{
				if(array_key_exists($value['_NAME'], $this->endnoteXmlFields) && 
					($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
					$this->map->{$type}['resource_creator'])))
				{
					$this->entry[$mapKey][] = $value['_DATA'];
					continue;
				}
// Endnote stores a patent's international author in the tertiary-title field and the international title 
// in the tertiary-author field.  Why I ask you?
				if(($type == 'patent') && 
					($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
					$this->map->{$type}['resource'])) && 
					($value['_NAME'] == 'TERTIARY_AUTHORS'))
				{
					$this->entry['resource'][$mapKey] = $value['_DATA'];
					continue;
				}
				$this->reject[$value['_NAME']] = $value['_DATA'];
			}
		}
	}
/* extractContributors()
*
* @author Mark Grimshaw
* @param $array - array of contributors
* @param $type - WIKINDX resource type
*
*/
	function extractContributors($array, $type)
	{
		foreach($array as $value)
		{
			if(array_key_exists("_NAME", $value) && array_key_exists("_ELEMENTS", $value))
			{
				foreach($value['_ELEMENTS'] as $authorArray)
				{
					if(array_key_exists($value['_NAME'], $this->endnoteXmlFields) && 
						($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
						$this->map->{$type}['resource_creator'])))
					{
						$this->entry[$mapKey][] = $authorArray['_DATA'];
						continue;
					}
// Endnote stores a patent's international author in the tertiary-title field and the international title 
// in the tertiary-author field.  Why I ask you?
					if(($type == 'patent') && 
						($mapKey = array_search($this->endnoteXmlFields[$value['_NAME']], 
						$this->map->{$type}['resource'])) && 
						($value['_NAME'] == 'tertiary-authors'))
					{
						$this->entry['resource'][$mapKey] = $authorArray['_DATA'];
						continue;
					}
					$this->reject[$value['_NAME']] = $authorArray['_DATA'];
				}
			}
		}
	}
/* extractUrl()
*
* @author Mark Grimshaw
* @param $array - array of urls
* @param $type - WIKINDX resource type
*
*/
	function extractUrl($array, $type)
	{
		foreach($array as $value)
		{
			if(array_key_exists("_NAME", $value) && array_key_exists("_ELEMENTS", $value) && 
				($value['_NAME'] == 'related-urls'))
			{
				foreach($value['_ELEMENTS'] as $urlArray)
				{
					if(array_key_exists("_NAME", $urlArray) && ($urlArray['_NAME'] == 'url') && 
						array_key_exists($urlArray['_NAME'], $this->endnoteXmlFields) && 
						($mapKey = array_search($this->endnoteXmlFields[$urlArray['_NAME']], 
						$this->map->{$type}['resource'])))
					{
						$this->entry['resource'][$mapKey] = $urlArray['_DATA'];
						continue;
					}
					$this->reject[$urlArray['_NAME']] = $urlArray['_DATA'];
				}
			}
		}
	}
// Write the bibtexKey field
	function writeBibtexKey()
	{
		$recordset = $this->db->select(array('WKX_resource'), 'bibtexKey');
		while($row = $this->db->loopRecordSet($recordset))
			$bibtexKeys[] = $row['bibtexKey'];
		$letters = range('a', 'z');
		$sizeof = sizeof($letters);
		$recordset = $this->db->select(array('WKX_resource_misc'), 
			array(array('WKX_resource_misc.id' => 'resourceId'), 'creator1', 'creator2', 'year1'), 
			" LEFT JOIN " . $this->db->formatTable('WKX_resource_creator') . ' ON ' . 
			$this->db->formatField('WKX_resource_misc.id') . '=' . 
			$this->db->formatField('WKX_resource_creator.id') . 
			" LEFT JOIN " . $this->db->formatTable('WKX_resource_year') . ' ON ' . 
			$this->db->formatField('WKX_resource_misc.id') . '=' . 
			$this->db->formatField('WKX_resource_year.id') . 
			' WHERE ' . $this->db->formatField('WKX_resource_misc.id') . "=" . $this->resourceId);
		$row = $this->db->fetchRow($recordset);
		$year = $row['year1'];
		if(!$row['creator1'] && $row['creator2']) // use editor
			$creatorId = array_shift(split(',', $row['creator2']));
		else
			$creatorId = array_shift(split(',', $row['creator1']));
		$recordset2 = $this->db->select(array('WKX_creator'), array('prefix', 'surname'), 
			' WHERE ' . $this->db->formatField('WKX_creator.id') . '=' . 
			$this->db->tidyInput($creatorId));
		$keyMade = FALSE;
		if(!$this->db->numRows($recordset2)) // anonymous
			$base = 'anon' . $year;
		else
		{
			$creator = $this->db->fetchRow($recordset2);
			$prefix = '';
			if($creator['prefix'])
			{
				$prefix = utf8_decode($creator['prefix']);
				$prefix = preg_replace("/\W/", '', $prefix);
			}
			$surname = utf8_decode($creator['surname']);
			$surname = preg_replace("/\W/", '', $surname);
			$base = $prefix . $surname . $year;
		}
		$bibtexKey = $base;
		for($i = 0; $i < $sizeof; $i++)
		{
			if(array_search($bibtexKey, $bibtexKeys) === FALSE)
			{
				$keyMade = TRUE;
				break;
			}
			$bibtexKey = $base . $letters[$i];
		}
		if(!$keyMade)
			$bibtexKey = $base . '.' . $this->resourceId; // last resort
		$this->db->updateSingle('WKX_resource', 
			$this->db->formatField('bibtexKey') .  "=" . $this->db->tidyInput($bibtexKey),
			" WHERE " . $this->db->formatField('id') . "=" . $this->resourceId);
	}
/*
* badInput - error handling - send user back to previous stage.
* 
* @author Mark Grimshaw
* @param string $error - any error message
*/
	function badInput($error)
	{
		include_once("core/template/TEMPLATE.php");
		$template = new TEMPLATE('content');
		include_once("core/file/import/ENDNOTEIMPORTSTAGE1.php");
		$stage = new ENDNOTEIMPORTSTAGE1($this->db, $this->vars);
		include_once("core/html/CLOSE.php");
		$template->setVar('heading', $this->messages->text("heading", "endnoteImport"));
		$template->setVar('formStart', FORM::formMultiHeader("importEndnoteStage2"));
		$template->setVar('body', $stage->init($error));
		$template->setVar('formEnd', FORM::formEnd());
		new CLOSE($this->db, $template->process());
	}
}
?>
